#include <ZipHelper.h>

#include <string.h>
#include <zlib.h>

const unsigned short CHUNK = 16384;

std::string ZipHelper::compressStream( const std::string& stream, unsigned char compressionLevel )
{
    if ( stream.empty() )
        return std::string();

    compressionLevel = compressionLevel > 9 ? 9 : compressionLevel;

    bool eos = false;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];
    std::string result;

    z_stream strm;

    if( deflateInit( &strm, compressionLevel ) != Z_OK )
        return std::string();

    const size_t strmSize = stream.size();
    size_t bytesToCopy = 0, totalBytesCopied = 0;
    do{
        bytesToCopy = strmSize - totalBytesCopied < CHUNK ? strmSize - totalBytesCopied : CHUNK;

        memcpy( in, stream.c_str() + totalBytesCopied, bytesToCopy );
        strm.avail_in = bytesToCopy;
        strm.next_in = in;
        strm.avail_out = CHUNK;
        strm.next_out = out;

        totalBytesCopied += bytesToCopy;
        eos = totalBytesCopied == strmSize;

        if( deflate( &strm, eos ? Z_FINISH : Z_NO_FLUSH ) == Z_STREAM_ERROR )
        {
            deflateEnd( &strm );
            return std::string ();
        }

        char buffer[CHUNK];
        memcpy( buffer, out, CHUNK - strm.avail_out );
        result.append( buffer, CHUNK - strm.avail_out );

    }while( !eos );

    return result;
}

//std::string ZipHelper::decompressStrm( const std::string& sourceStr, unsigned long uncompressedLen )
//{
//    unsigned int sourceSize = sourceStr.size();
//    const char * source = sourceStr.c_str();
//
//    char * destination = new char[uncompressedLen];
//
//    int result = uncompress( (unsigned char *)destination, &uncompressedLen, (const unsigned char *)source, sourceSize );
//    destination[uncompressedLen-1] = '\0';
//
//    if( result != Z_OK )
//        return std::string();
//
//    return destination;
//}
